package com.iweb.servlet.front;

import com.alibaba.fastjson.JSON;
import com.iweb.constant.CartItemChangeEnum;
import com.iweb.constant.LoginAction;
import com.iweb.constant.MyConstant;
import com.iweb.constant.ShoppingCartAction;
import com.iweb.entity.*;
import com.iweb.service.OrderService;
import com.iweb.service.ProductService;
import com.iweb.service.impl.OrderServiceImpl;
import com.iweb.service.impl.ProductServiceImpl;
import com.iweb.servlet.BaseServlet;
import com.iweb.util.StringHelper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.UUID;

/**
 * @author jay
 * @date 2021/9/14
 * @description
 */
@WebServlet(name = "shoppingCartServlet", urlPatterns = {"/front/shoppingCart.do"})
public class ShoppingCartServlet extends BaseServlet {

    private ProductService productService = new ProductServiceImpl();
    private OrderService orderService = new OrderServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = req.getParameter("action");
        if (ShoppingCartAction.OPEN.equals(action)) {
            // 打开购物车页面
            open(req, resp);
            return;
        }
        if (ShoppingCartAction.ADD.equals(action)) {
            // 加入商品到购物车
            add(req, resp);
            return;
        }
        if (ShoppingCartAction.REMOVE.equals(action)) {
            // 删除购物车中的商品
            remove(req, resp);
            return;
        }
        if (ShoppingCartAction.CHANGEAMOUNT.equals(action)) {
            // 修改购物车中的商品数量
            changeAmount(req, resp);
            return;
        }
        if (ShoppingCartAction.PAY.equals(action)) {
            // 生成订单并支付
            pay(req, resp);
            return;
        }
    }

    // 生成订单并支付
    private void pay(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建新的订单数据和订单项数据
        ShoppingCart myShoppingCart = this.findMyShoppingCart(req);
        // 判断是否为空购物车
        if (myShoppingCart.getTotalPrice() == null
                || myShoppingCart.getTotalPrice().equals(0.0)) {
            // 设置错误信息
            req.setAttribute("errorMessage", "当前购物车为空，请购物后再结算");
            this.open(req, resp);
        }
        // 获取登录对象
        User loginUser = (User) req.getSession().getAttribute("loginUser");
        if (loginUser == null) {
            // 要去登录
            resp.sendRedirect(req.getContextPath() + "/login.do&action=" + LoginAction.OPEN);
        }
        // 生成订单数据
        Order order = new Order();
        // 订单总价格
        order.setCost(myShoppingCart.getTotalPrice());
        order.setLoginName(loginUser.getLoginName());
        order.setCreateTime(new Date());
        order.setUserAddress("");
        order.setSerialNumber(UUID.randomUUID().toString());
        order.setUserId(loginUser.getId());
        // 添加订单详情数据
        OrderDetail orderDetail = null;
        for (ShoppingCartItem item : myShoppingCart.getItemList()) {
            orderDetail = new OrderDetail();
            // 小计价格
            orderDetail.setCost(item.getSum());
            orderDetail.setQuantity(item.getAmount());
            orderDetail.setProductId(item.getProductId());
            order.getOrderDetailList().add(orderDetail);
        }
        // 订单数据入库操作
        boolean result = orderService.add(order);
        // TODO: 跳转到显示界面

    }

    /**
     * 修改购物车中的商品数量
     *
     * @param req
     * @param resp
     */
    private void changeAmount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String sId = req.getParameter("productId");
        if (StringHelper.isEmpty(sId)) {
            return;
        }
        try {
            Integer productId = Integer.valueOf(sId);
            String option = req.getParameter("option");
            CartItemChangeEnum changeEnum = Enum.valueOf(CartItemChangeEnum.class, option);

            // 取出当前session中的购物车
            ShoppingCart myShoppingCart = this.findMyShoppingCart(req);

            // 修改数量
            myShoppingCart.changeAmount(productId, changeEnum);


            // 更新session中的购物车
            req.getSession().setAttribute("shoppingCart", myShoppingCart);

            // 把session中最新的购物车数据，写入到cookie
            this.writeCartToCookie(req, resp);

            // 打开购车车，查看修改情况
            this.open(req, resp);

        } catch (Exception e) {
            // 设置错误信息
            req.setAttribute("errorMessage", e.getMessage());
            // 跳转到美化后的错误处理界面
            req.getRequestDispatcher(MyConstant.JSPPREFIX + "500.jsp").forward(req, resp);
        }

    }

    /**
     * 删除购物车中的商品
     *
     * @param req
     * @param resp
     */
    private void remove(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String sId = req.getParameter("productId");
        if (StringHelper.isEmpty(sId)) {
            req.getRequestDispatcher(MyConstant.JSPPREFIX + "404.jsp").forward(req, resp);
            return;
        }
        try {
            Integer productId = Integer.valueOf(sId);
            // 取出当前session中的购物车
            ShoppingCart myShoppingCart = this.findMyShoppingCart(req);
            // 执行删除操作
            myShoppingCart.removeItem(productId);
            // 更新session中的购物车
            req.getSession().setAttribute("shoppingCart", myShoppingCart);

            // 把session中最新的购物车数据，写入到cookie
            this.writeCartToCookie(req, resp);

            // 打开购车车，查看添加情况
            this.open(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            // 设置错误信息
            req.setAttribute("errorMessage", e.getMessage());
            // 跳转到美化后的错误处理界面
            req.getRequestDispatcher(MyConstant.JSPPREFIX + "500.jsp").forward(req, resp);
        }
    }

    // 加入商品到购物车
    private void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String sId = req.getParameter("productId");
        if (StringHelper.isEmpty(sId)) {
            return;
        }
        try {
            Integer productId = Integer.valueOf(sId);
            // 查询商品信息
            Product product = this.productService.findById(productId);
            if (product == null) {
                return;
            }

            // 取出当前session中的购物车
            ShoppingCart myShoppingCart = this.findMyShoppingCart(req);
            // 添加商品到购物车
            myShoppingCart.addItem(product);

            // 更新session中的购物车
            req.getSession().setAttribute("shoppingCart", myShoppingCart);

            // 把session中最新的购物车数据，写入到cookie
            this.writeCartToCookie(req, resp);

            // 打开购车车，查看添加情况
            this.open(req, resp);

        } catch (Exception e) {
            // 设置错误信息
            req.setAttribute("errorMessage", e.getMessage());
            // 跳转到美化后的错误处理界面
            req.getRequestDispatcher(MyConstant.JSPPREFIX + "500.jsp").forward(req, resp);
        }
    }

    /**
     * 打开购物车页面
     *
     * @param req
     * @param resp
     */
    private void open(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        //  判断是否为第一次打开,只有第一次打开页面时，才从cookie中读取数据
        ShoppingCart shoppingCart = (ShoppingCart) req.getSession().getAttribute("shoppingCart");
        if (shoppingCart == null) {
            // 判断cookie中是否有购物车数据
            shoppingCart = this.readCartFromCookie(req);
            if (shoppingCart != null) {
                // 把当前从cookie中获取到的购物车对象，保存到session中
                req.getSession().setAttribute("shoppingCart", shoppingCart);
            }
        }

        // 跳转到购物车页面
        req.getRequestDispatcher(MyConstant.JSPPREFIX + "front/shoppingcart.jsp").forward(req, resp);
    }


    /**
     * 从cookie中读取购物车数据
     *
     * @param req
     * @return
     * @throws UnsupportedEncodingException
     */
    private ShoppingCart readCartFromCookie(HttpServletRequest req) throws UnsupportedEncodingException {
        ShoppingCart shoppingCart = null;
        // 读取本地cookie中的购物车数据
        Cookie[] cookies = req.getCookies();
        // 保存从cookie中获取到的购物车字符串
        String cartValue = null;
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("shoppingCart")) {
                    cartValue = cookie.getValue();
                    break;
                }
            }
        }

        // 处理并解析获取到的购物车字符串
        if (!StringHelper.isEmpty(cartValue)) {
            // 解码
            String decodeStr = URLDecoder.decode(cartValue, "utf-8");
            shoppingCart = JSON.parseObject(decodeStr, ShoppingCart.class);
        }
        return shoppingCart;
    }

    private void writeCartToCookie(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException {
        // 获取购物车
        ShoppingCart shoppingCart = (ShoppingCart) req.getSession().getAttribute("shoppingCart");
        if (shoppingCart == null) {
            return;
        }
        // 把购物车数据格化成JSON字符串，保存到cookie
        String jsonString = JSON.toJSONString(shoppingCart);
        // 进行编码后再存入cookie，防止乱码
        String encodeStr = URLEncoder.encode(jsonString, "utf-8");
        // 创建cookie对象
        Cookie cookie = new Cookie("shoppingCart", encodeStr);
        // 设置有效期 5分钟，保存在浏览器本地的时间
        cookie.setMaxAge(60 * 5);
        // 添加cookie到response, 以便在合适的时机回写数据到客户端
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }

    /**
     * 获取当前会话的购物车对象
     */
    private ShoppingCart findMyShoppingCart(HttpServletRequest req) {
        ShoppingCart shoppingCart = (ShoppingCart) req.getSession().getAttribute("shoppingCart");
        if (shoppingCart == null) {
            // 第一次打开，是没有购物车对象
            // 创建购物车对象
            shoppingCart = new ShoppingCart();
            // 保存购物车
            req.getSession().setAttribute("shoppingCart", shoppingCart);
        }
        return shoppingCart;
    }
}
